package epoch.game.core.distr.netty;

import java.util.concurrent.TimeUnit;

import epoch.game.core.distr.INodeConnector;
import epoch.game.core.distr.RemoteNode;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoop;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

public class NodeConnector implements INodeConnector {

	private EventLoopGroup eventLoop = new NioEventLoopGroup();

	public NodeConnector() {
	}

	@Override
	public void connect(RemoteNode remote, long timeout) {
		Bootstrap bootstrap = new Bootstrap();
		final NodeOutboundHandler handler = new NodeOutboundHandler(remote);
		bootstrap.group(eventLoop);
		bootstrap.channel(NioSocketChannel.class);
		bootstrap.option(ChannelOption.SO_KEEPALIVE, true);
		bootstrap.handler(new ChannelInitializer<SocketChannel>() {
			@Override
			protected void initChannel(SocketChannel socketChannel) throws Exception {
				socketChannel.pipeline().addLast(handler);
			}
		});
		bootstrap.remoteAddress(remote.getHost(), remote.getPort());
		bootstrap.connect().addListener(new ChannelFutureListener() {
			@Override
			public void operationComplete(ChannelFuture future) throws Exception {
				if (!future.isSuccess()) {
					final EventLoop loop = future.channel().eventLoop();
					loop.schedule(new Runnable() {
						@Override
						public void run() {
							connect(remote, timeout);
						}
					}, 1L, TimeUnit.SECONDS);
				}
			}
			
		});
	}

}
